/*
 * Copyright 2008 - 2010 Lars Heuer (heuer[at]semagia.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.semagia.mio.rdf.sesame;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.semagia.mio.IRef;
import com.semagia.mio.helpers.Ref;

/**
 * {@link ILanguageTagProvider} implementation which uses the 
 * <a href="http://psi.oasis-open.org/iso/639/">ISO 639 PSIs</a> published by 
 * <a href="http://www.oasis-open.org/">OASIS</a>.
 * 
 * @author Lars Heuer (heuer[at]semagia.com) <a href="http://www.semagia.com/">Semagia</a>
 * @version $Rev: 473 $ - $Date: 2010-09-08 11:36:04 +0000 (Wed, 08 Sep 2010) $
 */
final class OasisLanguageTagProvider implements ILanguageTagProvider {

    private static final Logger _LOG = LoggerFactory.getLogger(OasisLanguageTagProvider.class);

    private static final String _OASIS_BASE = "http://psi.oasis-open.org/iso/639/#";

    private static ILanguageTagProvider _INSTANCE = new OasisLanguageTagProvider();

    private OasisLanguageTagProvider() {
        // noop.
    }

    public static final ILanguageTagProvider getInstance() {
        return _INSTANCE ;
    }

    /* (non-Javadoc)
     * @see com.semagia.mio.rdf.sesame.ILanguageTagProvider#getLanguage(java.lang.String)
     */
    @Override
    public IRef getLanguage(final String lang) {
        if (lang == null) {
            return null;
        }
        final String langFragment = _getFragment(lang);
        if (langFragment == null) {
            _LOG.warn("Found no OASIS PSI for '{}'", lang);
            return null;
        }
        return Ref.createSubjectIdentifier(_OASIS_BASE + langFragment);
    }

    private static String _getFragment(final String lang) {
        final String normalizedLang = lang.toLowerCase();
        final char[] ch = normalizedLang.toCharArray();
        if (ch.length == 2) {
            return _resolveAlpha2Code(ch);
        }
        else if (ch.length == 3) {
            return _resolveAlpha3Code(ch, normalizedLang);
        }
        return null;
    }

    /**
     * Returns the OASIS fragment identifier for the provided alpha-3 code.
     * The alpha-3 code may be a bibliographic or terminologic code.
     *
     * @param ch The alpha-3 code.
     * @param lang The normalized (lower-case) language.
     * @return An OASIS fragment identifier or {@code null} if the alpha-3 code 
     *          is unknown.
     */
    private static String _resolveAlpha3Code(final char[] ch, final String lang) {
        // DO NOT EDIT, generated by a Python script
        switch (ch[0]) {
            case 'a':
                switch (ch[1]) {
                    case 'a':
                            return ch[2] == 'r' ? lang : null;
                    case 'b':
                            return ch[2] == 'k' ? lang : null;
                    case 'c':
                        switch (ch[2]) {
                            case 'e': return lang;
                            case 'h': return lang;
                        }
                        break;
                    case 'd':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'y': return lang;
                        }
                        break;
                    case 'f':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'h': return lang;
                            case 'r': return lang;
                        }
                        break;
                    case 'i':
                            return ch[2] == 'n' ? lang : null;
                    case 'k':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'k': return lang;
                        }
                        break;
                    case 'l':
                        switch (ch[2]) {
                            case 'b': return "sqi";
                            case 'e': return lang;
                            case 'g': return lang;
                            case 't': return lang;
                        }
                        break;
                    case 'm':
                            return ch[2] == 'h' ? lang : null;
                    case 'n':
                        switch (ch[2]) {
                            case 'g': return lang;
                            case 'p': return lang;
                        }
                        break;
                    case 'p':
                            return ch[2] == 'a' ? lang : null;
                    case 'r':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'c': return lang;
                            case 'g': return lang;
                            case 'm': return "hye";
                            case 'n': return lang;
                            case 'p': return lang;
                            case 't': return lang;
                            case 'w': return lang;
                        }
                        break;
                    case 's':
                        switch (ch[2]) {
                            case 'm': return lang;
                            case 't': return lang;
                        }
                        break;
                    case 't':
                            return ch[2] == 'h' ? lang : null;
                    case 'u':
                            return ch[2] == 's' ? lang : null;
                    case 'v':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'e': return lang;
                        }
                        break;
                    case 'w':
                            return ch[2] == 'a' ? lang : null;
                    case 'y':
                            return ch[2] == 'm' ? lang : null;
                    case 'z':
                            return ch[2] == 'e' ? lang : null;
                }
                break;
            case 'b':
                switch (ch[1]) {
                    case 'a':
                        switch (ch[2]) {
                            case 'd': return lang;
                            case 'i': return lang;
                            case 'k': return lang;
                            case 'l': return lang;
                            case 'm': return lang;
                            case 'n': return lang;
                            case 'q': return "eus";
                            case 's': return lang;
                            case 't': return lang;
                        }
                        break;
                    case 'e':
                        switch (ch[2]) {
                            case 'j': return lang;
                            case 'l': return lang;
                            case 'm': return lang;
                            case 'n': return lang;
                            case 'r': return lang;
                        }
                        break;
                    case 'h':
                            return ch[2] == 'o' ? lang : null;
                    case 'i':
                        switch (ch[2]) {
                            case 'h': return lang;
                            case 'k': return lang;
                            case 'n': return lang;
                            case 's': return lang;
                        }
                        break;
                    case 'l':
                            return ch[2] == 'a' ? lang : null;
                    case 'n':
                            return ch[2] == 't' ? lang : null;
                    case 'o':
                        switch (ch[2]) {
                            case 'd': return lang;
                            case 's': return lang;
                        }
                        break;
                    case 'r':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'e': return lang;
                        }
                        break;
                    case 't':
                            return ch[2] == 'k' ? lang : null;
                    case 'u':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'g': return lang;
                            case 'l': return lang;
                            case 'r': return "mya";
                        }
                        break;
                    case 'y':
                            return ch[2] == 'n' ? lang : null;
                }
                break;
            case 'c':
                switch (ch[1]) {
                    case 'a':
                        switch (ch[2]) {
                            case 'd': return lang;
                            case 'i': return lang;
                            case 'r': return lang;
                            case 't': return lang;
                            case 'u': return lang;
                        }
                        break;
                    case 'e':
                        switch (ch[2]) {
                            case 'b': return lang;
                            case 'l': return lang;
                            case 's': return lang;
                        }
                        break;
                    case 'h':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'b': return lang;
                            case 'e': return lang;
                            case 'g': return lang;
                            case 'i': return "zho";
                            case 'k': return lang;
                            case 'm': return lang;
                            case 'n': return lang;
                            case 'o': return lang;
                            case 'p': return lang;
                            case 'r': return lang;
                            case 'u': return lang;
                            case 'v': return lang;
                            case 'y': return lang;
                        }
                        break;
                    case 'm':
                            return ch[2] == 'c' ? lang : null;
                    case 'o':
                        switch (ch[2]) {
                            case 'p': return lang;
                            case 'r': return lang;
                            case 's': return lang;
                        }
                        break;
                    case 'p':
                        switch (ch[2]) {
                            case 'e': return lang;
                            case 'f': return lang;
                            case 'p': return lang;
                        }
                        break;
                    case 'r':
                        switch (ch[2]) {
                            case 'e': return lang;
                            case 'h': return lang;
                            case 'p': return lang;
                        }
                        break;
                    case 's':
                            return ch[2] == 'b' ? lang : null;
                    case 'u':
                            return ch[2] == 's' ? lang : null;
                    case 'y':
                            return ch[2] == 'm' ? lang : null;
                    case 'z':
                            return ch[2] == 'e' ? "ces" : null;
                }
                break;
            case 'd':
                switch (ch[1]) {
                    case 'a':
                        switch (ch[2]) {
                            case 'k': return lang;
                            case 'n': return lang;
                            case 'r': return lang;
                            case 'y': return lang;
                        }
                        break;
                    case 'e':
                        switch (ch[2]) {
                            case 'l': return lang;
                            case 'n': return lang;
                            case 'u': return lang;
                        }
                        break;
                    case 'g':
                            return ch[2] == 'r' ? lang : null;
                    case 'i':
                        switch (ch[2]) {
                            case 'n': return lang;
                            case 'v': return lang;
                        }
                        break;
                    case 'o':
                            return ch[2] == 'i' ? lang : null;
                    case 'r':
                            return ch[2] == 'a' ? lang : null;
                    case 's':
                            return ch[2] == 'b' ? lang : null;
                    case 'u':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'm': return lang;
                            case 't': return "nld";
                        }
                        break;
                    case 'y':
                            return ch[2] == 'u' ? lang : null;
                    case 'z':
                            return ch[2] == 'o' ? lang : null;
                }
                break;
            case 'e':
                switch (ch[1]) {
                    case 'f':
                            return ch[2] == 'i' ? lang : null;
                    case 'g':
                            return ch[2] == 'y' ? lang : null;
                    case 'k':
                            return ch[2] == 'a' ? lang : null;
                    case 'l':
                        switch (ch[2]) {
                            case 'l': return lang;
                            case 'x': return lang;
                        }
                        break;
                    case 'n':
                        switch (ch[2]) {
                            case 'g': return lang;
                            case 'm': return lang;
                        }
                        break;
                    case 'p':
                            return ch[2] == 'o' ? lang : null;
                    case 's':
                            return ch[2] == 't' ? lang : null;
                    case 'u':
                            return ch[2] == 's' ? lang : null;
                    case 'w':
                        switch (ch[2]) {
                            case 'e': return lang;
                            case 'o': return lang;
                        }
                        break;
                }
                break;
            case 'f':
                switch (ch[1]) {
                    case 'a':
                        switch (ch[2]) {
                            case 'n': return lang;
                            case 'o': return lang;
                            case 's': return lang;
                            case 't': return lang;
                        }
                        break;
                    case 'i':
                        switch (ch[2]) {
                            case 'j': return lang;
                            case 'l': return lang;
                            case 'n': return lang;
                            case 'u': return lang;
                        }
                        break;
                    case 'o':
                            return ch[2] == 'n' ? lang : null;
                    case 'r':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'e': return "fra";
                            case 'm': return lang;
                            case 'o': return lang;
                            case 'r': return lang;
                            case 's': return lang;
                            case 'y': return lang;
                        }
                        break;
                    case 'u':
                        switch (ch[2]) {
                            case 'l': return lang;
                            case 'r': return lang;
                        }
                        break;
                }
                break;
            case 'g':
                switch (ch[1]) {
                    case 'a':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'y': return lang;
                        }
                        break;
                    case 'b':
                            return ch[2] == 'a' ? lang : null;
                    case 'e':
                        switch (ch[2]) {
                            case 'm': return lang;
                            case 'o': return "kat";
                            case 'r': return "deu";
                            case 'z': return lang;
                        }
                        break;
                    case 'i':
                            return ch[2] == 'l' ? lang : null;
                    case 'l':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'e': return lang;
                            case 'g': return lang;
                            case 'v': return lang;
                        }
                        break;
                    case 'm':
                            return ch[2] == 'h' ? lang : null;
                    case 'o':
                        switch (ch[2]) {
                            case 'h': return lang;
                            case 'n': return lang;
                            case 'r': return lang;
                            case 't': return lang;
                        }
                        break;
                    case 'r':
                        switch (ch[2]) {
                            case 'b': return lang;
                            case 'c': return lang;
                            case 'e': return "ell";
                            case 'n': return lang;
                        }
                        break;
                    case 's':
                            return ch[2] == 'w' ? lang : null;
                    case 'u':
                            return ch[2] == 'j' ? lang : null;
                    case 'w':
                            return ch[2] == 'i' ? lang : null;
                }
                break;
            case 'h':
                switch (ch[1]) {
                    case 'a':
                        switch (ch[2]) {
                            case 'i': return lang;
                            case 't': return lang;
                            case 'u': return lang;
                            case 'w': return lang;
                        }
                        break;
                    case 'e':
                        switch (ch[2]) {
                            case 'b': return lang;
                            case 'r': return lang;
                        }
                        break;
                    case 'i':
                        switch (ch[2]) {
                            case 'l': return lang;
                            case 'm': return lang;
                            case 'n': return lang;
                            case 't': return lang;
                        }
                        break;
                    case 'm':
                        switch (ch[2]) {
                            case 'n': return lang;
                            case 'o': return lang;
                        }
                        break;
                    case 'r':
                            return ch[2] == 'v' ? lang : null;
                    case 's':
                            return ch[2] == 'b' ? lang : null;
                    case 'u':
                        switch (ch[2]) {
                            case 'n': return lang;
                            case 'p': return lang;
                        }
                        break;
                    case 'y':
                            return ch[2] == 'e' ? lang : null;
                }
                break;
            case 'i':
                switch (ch[1]) {
                    case 'b':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'o': return lang;
                        }
                        break;
                    case 'c':
                            return ch[2] == 'e' ? "isl" : null;
                    case 'd':
                            return ch[2] == 'o' ? lang : null;
                    case 'i':
                            return ch[2] == 'i' ? lang : null;
                    case 'j':
                            return ch[2] == 'o' ? lang : null;
                    case 'k':
                            return ch[2] == 'u' ? lang : null;
                    case 'l':
                        switch (ch[2]) {
                            case 'e': return lang;
                            case 'o': return lang;
                        }
                        break;
                    case 'n':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'c': return lang;
                            case 'd': return lang;
                            case 'e': return lang;
                            case 'h': return lang;
                        }
                        break;
                    case 'p':
                            return ch[2] == 'k' ? lang : null;
                    case 'r':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'o': return lang;
                        }
                        break;
                    case 's':
                            return ch[2] == 'l' ? lang : null;
                    case 't':
                            return ch[2] == 'a' ? lang : null;
                }
                break;
            case 'j':
                switch (ch[1]) {
                    case 'a':
                            return ch[2] == 'v' ? lang : null;
                    case 'b':
                            return ch[2] == 'o' ? lang : null;
                    case 'p':
                        switch (ch[2]) {
                            case 'n': return lang;
                            case 'r': return lang;
                        }
                        break;
                    case 'r':
                            return ch[2] == 'b' ? lang : null;
                }
                break;
            case 'k':
                switch (ch[1]) {
                    case 'a':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'b': return lang;
                            case 'c': return lang;
                            case 'l': return lang;
                            case 'm': return lang;
                            case 'n': return lang;
                            case 'r': return lang;
                            case 's': return lang;
                            case 't': return lang;
                            case 'u': return lang;
                            case 'w': return lang;
                            case 'z': return lang;
                        }
                        break;
                    case 'b':
                            return ch[2] == 'd' ? lang : null;
                    case 'h':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'i': return lang;
                            case 'm': return lang;
                            case 'o': return lang;
                        }
                        break;
                    case 'i':
                        switch (ch[2]) {
                            case 'k': return lang;
                            case 'n': return lang;
                            case 'r': return lang;
                        }
                        break;
                    case 'm':
                            return ch[2] == 'b' ? lang : null;
                    case 'o':
                        switch (ch[2]) {
                            case 'k': return lang;
                            case 'm': return lang;
                            case 'n': return lang;
                            case 'r': return lang;
                            case 's': return lang;
                        }
                        break;
                    case 'p':
                            return ch[2] == 'e' ? lang : null;
                    case 'r':
                        switch (ch[2]) {
                            case 'c': return lang;
                            case 'l': return lang;
                            case 'o': return lang;
                            case 'u': return lang;
                        }
                        break;
                    case 'u':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'm': return lang;
                            case 'r': return lang;
                            case 't': return lang;
                        }
                        break;
                }
                break;
            case 'l':
                switch (ch[1]) {
                    case 'a':
                        switch (ch[2]) {
                            case 'd': return lang;
                            case 'h': return lang;
                            case 'm': return lang;
                            case 'o': return lang;
                            case 't': return lang;
                            case 'v': return lang;
                        }
                        break;
                    case 'e':
                            return ch[2] == 'z' ? lang : null;
                    case 'i':
                        switch (ch[2]) {
                            case 'm': return lang;
                            case 'n': return lang;
                            case 't': return lang;
                        }
                        break;
                    case 'o':
                        switch (ch[2]) {
                            case 'l': return lang;
                            case 'z': return lang;
                        }
                        break;
                    case 't':
                            return ch[2] == 'z' ? lang : null;
                    case 'u':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'b': return lang;
                            case 'g': return lang;
                            case 'i': return lang;
                            case 'n': return lang;
                            case 'o': return lang;
                            case 's': return lang;
                        }
                        break;
                }
                break;
            case 'm':
                switch (ch[1]) {
                    case 'a':
                        switch (ch[2]) {
                            case 'c': return "mkd";
                            case 'd': return lang;
                            case 'g': return lang;
                            case 'h': return lang;
                            case 'i': return lang;
                            case 'k': return lang;
                            case 'l': return lang;
                            case 'n': return lang;
                            case 'o': return "mri";
                            case 'p': return lang;
                            case 'r': return lang;
                            case 's': return lang;
                            case 'y': return "msa";
                        }
                        break;
                    case 'd':
                        switch (ch[2]) {
                            case 'f': return lang;
                            case 'r': return lang;
                        }
                        break;
                    case 'e':
                            return ch[2] == 'n' ? lang : null;
                    case 'g':
                            return ch[2] == 'a' ? lang : null;
                    case 'i':
                        switch (ch[2]) {
                            case 'c': return lang;
                            case 'n': return lang;
                            case 's': return lang;
                        }
                        break;
                    case 'k':
                        switch (ch[2]) {
                            case 'd': return lang;
                            case 'h': return lang;
                        }
                        break;
                    case 'l':
                        switch (ch[2]) {
                            case 'g': return lang;
                            case 't': return lang;
                        }
                        break;
                    case 'n':
                        switch (ch[2]) {
                            case 'c': return lang;
                            case 'i': return lang;
                            case 'o': return lang;
                        }
                        break;
                    case 'o':
                        switch (ch[2]) {
                            case 'h': return lang;
                            case 'n': return lang;
                            case 's': return lang;
                        }
                        break;
                    case 'r':
                            return ch[2] == 'i' ? lang : null;
                    case 's':
                            return ch[2] == 'a' ? lang : null;
                    case 'u':
                        switch (ch[2]) {
                            case 'l': return lang;
                            case 'n': return lang;
                            case 's': return lang;
                        }
                        break;
                    case 'w':
                        switch (ch[2]) {
                            case 'l': return lang;
                            case 'r': return lang;
                        }
                        break;
                    case 'y':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'n': return lang;
                            case 'v': return lang;
                        }
                        break;
                }
                break;
            case 'n':
                switch (ch[1]) {
                    case 'a':
                        switch (ch[2]) {
                            case 'h': return lang;
                            case 'i': return lang;
                            case 'p': return lang;
                            case 'u': return lang;
                            case 'v': return lang;
                        }
                        break;
                    case 'b':
                            return ch[2] == 'l' ? lang : null;
                    case 'd':
                        switch (ch[2]) {
                            case 'e': return lang;
                            case 'o': return lang;
                            case 's': return lang;
                        }
                        break;
                    case 'e':
                        switch (ch[2]) {
                            case 'p': return lang;
                            case 'w': return lang;
                        }
                        break;
                    case 'i':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'c': return lang;
                            case 'u': return lang;
                        }
                        break;
                    case 'l':
                            return ch[2] == 'd' ? lang : null;
                    case 'n':
                            return ch[2] == 'o' ? lang : null;
                    case 'o':
                        switch (ch[2]) {
                            case 'b': return lang;
                            case 'g': return lang;
                            case 'n': return lang;
                            case 'r': return lang;
                        }
                        break;
                    case 'q':
                            return ch[2] == 'o' ? lang : null;
                    case 's':
                            return ch[2] == 'o' ? lang : null;
                    case 'u':
                            return ch[2] == 'b' ? lang : null;
                    case 'w':
                            return ch[2] == 'c' ? lang : null;
                    case 'y':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'm': return lang;
                            case 'n': return lang;
                            case 'o': return lang;
                        }
                        break;
                    case 'z':
                            return ch[2] == 'i' ? lang : null;
                }
                break;
            case 'o':
                switch (ch[1]) {
                    case 'c':
                            return ch[2] == 'i' ? lang : null;
                    case 'j':
                            return ch[2] == 'i' ? lang : null;
                    case 'r':
                        switch (ch[2]) {
                            case 'i': return lang;
                            case 'm': return lang;
                        }
                        break;
                    case 's':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 's': return lang;
                        }
                        break;
                    case 't':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'o': return lang;
                        }
                        break;
                }
                break;
            case 'p':
                switch (ch[1]) {
                    case 'a':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'g': return lang;
                            case 'l': return lang;
                            case 'm': return lang;
                            case 'n': return lang;
                            case 'p': return lang;
                            case 'u': return lang;
                        }
                        break;
                    case 'e':
                        switch (ch[2]) {
                            case 'o': return lang;
                            case 'r': return "fas";
                        }
                        break;
                    case 'h':
                        switch (ch[2]) {
                            case 'i': return lang;
                            case 'n': return lang;
                        }
                        break;
                    case 'l':
                            return ch[2] == 'i' ? lang : null;
                    case 'o':
                        switch (ch[2]) {
                            case 'l': return lang;
                            case 'n': return lang;
                            case 'r': return lang;
                        }
                        break;
                    case 'r':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'o': return lang;
                        }
                        break;
                    case 'u':
                            return ch[2] == 's' ? lang : null;
                }
                break;
            case 'q':
                switch (ch[1]) {
                    case 'u':
                            return ch[2] == 'e' ? lang : null;
                }
                break;
            case 'r':
                switch (ch[1]) {
                    case 'a':
                        switch (ch[2]) {
                            case 'j': return lang;
                            case 'p': return lang;
                            case 'r': return lang;
                        }
                        break;
                    case 'o':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'h': return lang;
                            case 'm': return lang;
                            case 'n': return lang;
                        }
                        break;
                    case 'u':
                        switch (ch[2]) {
                            case 'm': return "ron";
                            case 'n': return lang;
                            case 'p': return lang;
                            case 's': return lang;
                        }
                        break;
                }
                break;
            case 's':
                switch (ch[1]) {
                    case 'a':
                        switch (ch[2]) {
                            case 'd': return lang;
                            case 'g': return lang;
                            case 'h': return lang;
                            case 'i': return lang;
                            case 'l': return lang;
                            case 'm': return lang;
                            case 'n': return lang;
                            case 's': return lang;
                            case 't': return lang;
                        }
                        break;
                    case 'c':
                        switch (ch[2]) {
                            case 'n': return lang;
                            case 'o': return lang;
                        }
                        break;
                    case 'e':
                        switch (ch[2]) {
                            case 'l': return lang;
                            case 'm': return lang;
                        }
                        break;
                    case 'g':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'n': return lang;
                        }
                        break;
                    case 'h':
                            return ch[2] == 'n' ? lang : null;
                    case 'i':
                        switch (ch[2]) {
                            case 'd': return lang;
                            case 'n': return lang;
                            case 'o': return lang;
                            case 't': return lang;
                        }
                        break;
                    case 'l':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'k': return lang;
                            case 'o': return "slk";
                            case 'v': return lang;
                        }
                        break;
                    case 'm':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'e': return lang;
                            case 'i': return lang;
                            case 'j': return lang;
                            case 'n': return lang;
                            case 'o': return lang;
                            case 's': return lang;
                        }
                        break;
                    case 'n':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'd': return lang;
                            case 'k': return lang;
                        }
                        break;
                    case 'o':
                        switch (ch[2]) {
                            case 'g': return lang;
                            case 'm': return lang;
                            case 'n': return lang;
                            case 't': return lang;
                        }
                        break;
                    case 'p':
                            return ch[2] == 'a' ? lang : null;
                    case 'q':
                            return ch[2] == 'i' ? lang : null;
                    case 'r':
                        switch (ch[2]) {
                            case 'd': return lang;
                            case 'n': return lang;
                            case 'p': return lang;
                            case 'r': return lang;
                        }
                        break;
                    case 's':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'w': return lang;
                        }
                        break;
                    case 'u':
                        switch (ch[2]) {
                            case 'k': return lang;
                            case 'n': return lang;
                            case 's': return lang;
                            case 'x': return lang;
                        }
                        break;
                    case 'w':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'e': return lang;
                        }
                        break;
                    case 'y':
                        switch (ch[2]) {
                            case 'c': return lang;
                            case 'r': return lang;
                        }
                        break;
                }
                break;
            case 't':
                switch (ch[1]) {
                    case 'a':
                        switch (ch[2]) {
                            case 'h': return lang;
                            case 'i': return lang;
                            case 'm': return lang;
                            case 't': return lang;
                        }
                        break;
                    case 'e':
                        switch (ch[2]) {
                            case 'l': return lang;
                            case 'm': return lang;
                            case 'r': return lang;
                            case 't': return lang;
                        }
                        break;
                    case 'g':
                        switch (ch[2]) {
                            case 'k': return lang;
                            case 'l': return lang;
                        }
                        break;
                    case 'h':
                            return ch[2] == 'a' ? lang : null;
                    case 'i':
                        switch (ch[2]) {
                            case 'b': return "bod";
                            case 'g': return lang;
                            case 'r': return lang;
                            case 'v': return lang;
                        }
                        break;
                    case 'k':
                            return ch[2] == 'l' ? lang : null;
                    case 'l':
                        switch (ch[2]) {
                            case 'h': return lang;
                            case 'i': return lang;
                        }
                        break;
                    case 'm':
                            return ch[2] == 'h' ? lang : null;
                    case 'o':
                        switch (ch[2]) {
                            case 'g': return lang;
                            case 'n': return lang;
                        }
                        break;
                    case 'p':
                            return ch[2] == 'i' ? lang : null;
                    case 's':
                        switch (ch[2]) {
                            case 'i': return lang;
                            case 'n': return lang;
                            case 'o': return lang;
                        }
                        break;
                    case 'u':
                        switch (ch[2]) {
                            case 'k': return lang;
                            case 'm': return lang;
                            case 'p': return lang;
                            case 'r': return lang;
                            case 't': return lang;
                        }
                        break;
                    case 'v':
                            return ch[2] == 'l' ? lang : null;
                    case 'w':
                            return ch[2] == 'i' ? lang : null;
                    case 'y':
                            return ch[2] == 'v' ? lang : null;
                }
                break;
            case 'u':
                switch (ch[1]) {
                    case 'd':
                            return ch[2] == 'm' ? lang : null;
                    case 'g':
                            return ch[2] == 'a' ? lang : null;
                    case 'i':
                            return ch[2] == 'g' ? lang : null;
                    case 'k':
                            return ch[2] == 'r' ? lang : null;
                    case 'm':
                            return ch[2] == 'b' ? lang : null;
                    case 'n':
                            return ch[2] == 'd' ? lang : null;
                    case 'r':
                            return ch[2] == 'd' ? lang : null;
                    case 'z':
                            return ch[2] == 'b' ? lang : null;
                }
                break;
            case 'v':
                switch (ch[1]) {
                    case 'a':
                            return ch[2] == 'i' ? lang : null;
                    case 'e':
                            return ch[2] == 'n' ? lang : null;
                    case 'i':
                            return ch[2] == 'e' ? lang : null;
                    case 'o':
                        switch (ch[2]) {
                            case 'l': return lang;
                            case 't': return lang;
                        }
                        break;
                }
                break;
            case 'w':
                switch (ch[1]) {
                    case 'a':
                        switch (ch[2]) {
                            case 'k': return lang;
                            case 'l': return lang;
                            case 'r': return lang;
                            case 's': return lang;
                        }
                        break;
                    case 'e':
                        switch (ch[2]) {
                            case 'l': return "cym";
                            case 'n': return lang;
                        }
                        break;
                    case 'l':
                            return ch[2] == 'n' ? lang : null;
                    case 'o':
                            return ch[2] == 'l' ? lang : null;
                }
                break;
            case 'x':
                switch (ch[1]) {
                    case 'a':
                            return ch[2] == 'l' ? lang : null;
                    case 'h':
                            return ch[2] == 'o' ? lang : null;
                }
                break;
            case 'y':
                switch (ch[1]) {
                    case 'a':
                        switch (ch[2]) {
                            case 'o': return lang;
                            case 'p': return lang;
                        }
                        break;
                    case 'i':
                            return ch[2] == 'd' ? lang : null;
                    case 'o':
                            return ch[2] == 'r' ? lang : null;
                    case 'p':
                            return ch[2] == 'k' ? lang : null;
                }
                break;
            case 'z':
                switch (ch[1]) {
                    case 'a':
                            return ch[2] == 'p' ? lang : null;
                    case 'b':
                            return ch[2] == 'l' ? lang : null;
                    case 'e':
                            return ch[2] == 'n' ? lang : null;
                    case 'h':
                        switch (ch[2]) {
                            case 'a': return lang;
                            case 'o': return lang;
                        }
                        break;
                    case 'n':
                            return ch[2] == 'd' ? lang : null;
                    case 'u':
                        switch (ch[2]) {
                            case 'l': return lang;
                            case 'n': return lang;
                        }
                        break;
                    case 'x':
                            return ch[2] == 'x' ? lang : null;
                    case 'z':
                            return ch[2] == 'a' ? lang : null;
                }
                break;
        }
        return null;
    }

    /**
     * Returns the OASIS fragment for the provided alpha-2 code.
     *
     * @param ch The alpha-2 code.
     * @return An OASIS fragment identifier or {@code null} if the alpha-2 code 
     *          is unknown.
     */
    private static String _resolveAlpha2Code(final char[] ch) {
        // DO NOT EDIT, generated by a Python script
        switch (ch[0]) {
            case 'a':
                switch (ch[1]) {
                    case 'a': return "aar";
                    case 'b': return "abk";
                    case 'e': return "ave";
                    case 'f': return "afr";
                    case 'k': return "aka";
                    case 'm': return "amh";
                    case 'n': return "arg";
                    case 'r': return "ara";
                    case 's': return "asm";
                    case 'v': return "ava";
                    case 'y': return "aym";
                    case 'z': return "aze";
                }
                break;
            case 'b':
                switch (ch[1]) {
                    case 'a': return "bak";
                    case 'e': return "bel";
                    case 'g': return "bul";
                    case 'h': return "bih";
                    case 'i': return "bis";
                    case 'm': return "bam";
                    case 'n': return "ben";
                    case 'o': return "bod";
                    case 'r': return "bre";
                    case 's': return "bos";
                }
                break;
            case 'c':
                switch (ch[1]) {
                    case 'a': return "cat";
                    case 'e': return "che";
                    case 'h': return "cha";
                    case 'o': return "cos";
                    case 'r': return "cre";
                    case 's': return "ces";
                    case 'u': return "chu";
                    case 'v': return "chv";
                    case 'y': return "cym";
                }
                break;
            case 'd':
                switch (ch[1]) {
                    case 'a': return "dan";
                    case 'e': return "deu";
                    case 'v': return "div";
                    case 'z': return "dzo";
                }
                break;
            case 'e':
                switch (ch[1]) {
                    case 'e': return "ewe";
                    case 'l': return "ell";
                    case 'n': return "eng";
                    case 'o': return "epo";
                    case 's': return "spa";
                    case 't': return "est";
                    case 'u': return "eus";
                }
                break;
            case 'f':
                switch (ch[1]) {
                    case 'a': return "fas";
                    case 'f': return "ful";
                    case 'i': return "fin";
                    case 'j': return "fij";
                    case 'o': return "fao";
                    case 'r': return "fra";
                    case 'y': return "fry";
                }
                break;
            case 'g':
                switch (ch[1]) {
                    case 'a': return "gle";
                    case 'd': return "gla";
                    case 'l': return "glg";
                    case 'n': return "grn";
                    case 'u': return "guj";
                    case 'v': return "glv";
                }
                break;
            case 'h':
                switch (ch[1]) {
                    case 'a': return "hau";
                    case 'e': return "heb";
                    case 'i': return "hin";
                    case 'o': return "hmo";
                    case 'r': return "hrv";
                    case 't': return "hat";
                    case 'u': return "hun";
                    case 'y': return "hye";
                    case 'z': return "her";
                }
                break;
            case 'i':
                switch (ch[1]) {
                    case 'a': return "ina";
                    case 'd': return "ind";
                    case 'e': return "ile";
                    case 'g': return "ibo";
                    case 'i': return "iii";
                    case 'k': return "ipk";
                    case 'o': return "ido";
                    case 's': return "isl";
                    case 't': return "ita";
                    case 'u': return "iku";
                }
                break;
            case 'j':
                switch (ch[1]) {
                    case 'a': return "jpn";
                    case 'v': return "jav";
                }
                break;
            case 'k':
                switch (ch[1]) {
                    case 'a': return "kat";
                    case 'g': return "kon";
                    case 'i': return "kik";
                    case 'j': return "kua";
                    case 'k': return "kaz";
                    case 'l': return "kal";
                    case 'm': return "khm";
                    case 'n': return "kan";
                    case 'o': return "kor";
                    case 'r': return "kau";
                    case 's': return "kas";
                    case 'u': return "kur";
                    case 'v': return "kom";
                    case 'w': return "cor";
                    case 'y': return "kir";
                }
                break;
            case 'l':
                switch (ch[1]) {
                    case 'a': return "lat";
                    case 'b': return "ltz";
                    case 'g': return "lug";
                    case 'i': return "lim";
                    case 'n': return "lin";
                    case 'o': return "lao";
                    case 't': return "lit";
                    case 'u': return "lub";
                    case 'v': return "lav";
                }
                break;
            case 'm':
                switch (ch[1]) {
                    case 'g': return "mlg";
                    case 'h': return "mah";
                    case 'i': return "mri";
                    case 'k': return "mkd";
                    case 'l': return "mal";
                    case 'n': return "mon";
                    case 'r': return "mar";
                    case 's': return "msa";
                    case 't': return "mlt";
                    case 'y': return "mya";
                }
                break;
            case 'n':
                switch (ch[1]) {
                    case 'a': return "nau";
                    case 'b': return "nob";
                    case 'd': return "nde";
                    case 'e': return "nep";
                    case 'g': return "ndo";
                    case 'l': return "nld";
                    case 'n': return "nno";
                    case 'o': return "nor";
                    case 'r': return "nbl";
                    case 'v': return "nav";
                    case 'y': return "nya";
                }
                break;
            case 'o':
                switch (ch[1]) {
                    case 'c': return "oci";
                    case 'j': return "oji";
                    case 'm': return "orm";
                    case 'r': return "ori";
                    case 's': return "oss";
                }
                break;
            case 'p':
                switch (ch[1]) {
                    case 'a': return "pan";
                    case 'i': return "pli";
                    case 'l': return "pol";
                    case 's': return "pus";
                    case 't': return "por";
                }
                break;
            case 'q':
                    return ch[1] == 'u' ? "que" : null;
            case 'r':
                switch (ch[1]) {
                    case 'm': return "roh";
                    case 'n': return "run";
                    case 'o': return "ron";
                    case 'u': return "rus";
                    case 'w': return "kin";
                }
                break;
            case 's':
                switch (ch[1]) {
                    case 'a': return "san";
                    case 'c': return "srd";
                    case 'd': return "snd";
                    case 'e': return "sme";
                    case 'g': return "sag";
                    case 'i': return "sin";
                    case 'k': return "slk";
                    case 'l': return "slv";
                    case 'm': return "smo";
                    case 'n': return "sna";
                    case 'o': return "som";
                    case 'q': return "sqi";
                    case 'r': return "srp";
                    case 's': return "ssw";
                    case 't': return "sot";
                    case 'u': return "sun";
                    case 'v': return "swe";
                    case 'w': return "swa";
                }
                break;
            case 't':
                switch (ch[1]) {
                    case 'a': return "tam";
                    case 'e': return "tel";
                    case 'g': return "tgk";
                    case 'h': return "tha";
                    case 'i': return "tir";
                    case 'k': return "tuk";
                    case 'l': return "tgl";
                    case 'n': return "tsn";
                    case 'o': return "ton";
                    case 'r': return "tur";
                    case 's': return "tso";
                    case 't': return "tat";
                    case 'w': return "twi";
                    case 'y': return "tah";
                }
                break;
            case 'u':
                switch (ch[1]) {
                    case 'g': return "uig";
                    case 'k': return "ukr";
                    case 'r': return "urd";
                    case 'z': return "uzb";
                }
                break;
            case 'v':
                switch (ch[1]) {
                    case 'e': return "ven";
                    case 'i': return "vie";
                    case 'o': return "vol";
                }
                break;
            case 'w':
                switch (ch[1]) {
                    case 'a': return "wln";
                    case 'o': return "wol";
                }
                break;
            case 'x':
                    return ch[1] == 'h' ? "xho" : null;
            case 'y':
                switch (ch[1]) {
                    case 'i': return "yid";
                    case 'o': return "yor";
                }
                break;
            case 'z':
                switch (ch[1]) {
                    case 'a': return "zha";
                    case 'h': return "zho";
                    case 'u': return "zul";
                }
                break;
      }
      return null;
    }

}
